package one.stand.util;


import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * Created by chengjiarui on 2019-06-27.
 */
public class ZipUtil {

    /**
     * 提供给用户使用的解压工具
     *
     * @param srcPath
     * @param outPath
     * @throws IOException
     */
    public static void decompressionFile(String srcPath, String outPath) throws IOException {
        //简单判断解压路径是否合法
        if (!new File(srcPath).isDirectory()) {
            FileInputStream fileInputStream = new FileInputStream(srcPath);
            decompressionFile(fileInputStream, outPath);
        } else {
            throw new RuntimeException("需要解压的文件不合法!");
        }
    }

    /**
     * 提供给用户使用的解压工具
     *
     * @param fileInputStream
     * @param outPath
     * @throws IOException
     */
    public static void decompressionFile(InputStream fileInputStream, String outPath) throws IOException {
        //简单判断解压路径是否合法
        //判断输出路径是否合法
        if (new File(outPath).isDirectory()) {
            if (!outPath.endsWith(File.separator)) {
                outPath += File.separator;
            }
            //zip读取压缩文件
            Charset gbk = Charset.forName("GBK");
            ZipInputStream zipInputStream = new ZipInputStream(fileInputStream, gbk);
            //解压文件
            decompressionFile(outPath, zipInputStream);
            //关闭流
            zipInputStream.close();
            fileInputStream.close();
        } else {
            throw new RuntimeException("输出路径不合法!");
        }
    }

    /**
     * ZipInputStream是逐个目录进行读取，所以只需要循环
     *
     * @param outPath
     * @param inputStream
     * @throws IOException
     */
    private static void decompressionFile(String outPath, ZipInputStream inputStream) throws IOException {
        //读取一个目录
        ZipEntry nextEntry = inputStream.getNextEntry();
        //不为空进入循环
        while (nextEntry != null) {
            String name = nextEntry.getName();
            File file = new File(outPath + name);
            //如果是目录，创建目录
            if (name.endsWith("/")) {
                file.mkdir();
            } else {
                //文件则写入具体的路径中
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                int n;
                byte[] bytes = new byte[1024];
                while ((n = inputStream.read(bytes)) != -1) {
                    bufferedOutputStream.write(bytes, 0, n);
                }
                //关闭流
                bufferedOutputStream.close();
                fileOutputStream.close();
            }
            //关闭当前布姆
            inputStream.closeEntry();
            //读取下一个目录，作为循环条件
            nextEntry = inputStream.getNextEntry();
        }
    }

    /**
     * 解压方法
     *
     * @param parent 解压到目录下
     * @param zip    zip文件
     */
    public static void decompressed(String parent, String zip) {
        try {
            decompressed(new File(parent), new ZipFile(zip));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压方法
     *
     * @param parent 解压到目录下
     * @param zip    zip文件
     */
    public static void decompressed(File parent, File zip) {
        try {
            decompressed(parent, new ZipFile(zip));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压方法
     *
     * @param parent  解压到目录下
     * @param zipFile zip文件
     */
    public static void decompressed(File parent, ZipFile zipFile) {
        mkdirs(parent);
        try {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry zipEntry = entries.nextElement();
                File file = new File(parent, zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    mkdirs(file);
                } else {
                    createFile(file);
                    InputStream is = zipFile.getInputStream(zipEntry);
                    FileOutputStream fos = new FileOutputStream(file);
                    byte[] b = new byte[1024];
                    int len;
                    while ((len = is.read(b)) != -1) {
                        fos.write(b, 0, len);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建文件顺便创建父目录
     *
     * @param path 文件字符串路径例如d:/fulld/why/ass/a/asd
     */
    public static void createFile(String path) {
        createFile(new File(path));
    }

    /**
     * 创建文件顺便创建父目录
     *
     * @param file file类
     */
    public static void createFile(File file) {
        if (file.exists() && file.isFile()) {
            file.delete();
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        File parentFile = file.getParentFile();
        if (parentFile.exists()) {
            if (parentFile.isFile()) {
                parentFile.delete();
                parentFile.mkdirs();
            }
        } else {
            parentFile.mkdirs();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建文件夹顺便创建父目录
     *
     * @param path 文件夹的路径字符串例如d:/fulld/why/ass/a/asd/
     * @return 如果本来就存在或者创建成功，那么就返回true
     */
    public static void mkdirs(String path) {
        mkdirs(new File(path));
    }

    /**
     * 创建文件夹顺便创建父目录
     *
     * @param file file类
     */
    public static void mkdirs(File file) {
        if (file.exists() && file.isDirectory()) {
            return;
        }
        if (file.exists()) {//肯定是文件了，文件删掉
            file.delete();
            file.mkdirs();
        } else {
            file.mkdirs();
        }
    }
}
